/*
*	BooleanFormatter.h
*	  		Original code: William Shipley
*			Revised for string display: Mai Nguyen
*/

#import "BooleanFormatter.h"

#define _delWill1	@selector(formatterWillChangeValueFor:at:sender:)
#define _delWill2	@selector(formatterWillChangeValueFor:at:to:sender:)
#define _delDid		@selector(formatterDidChangeValueFor:at:to:sender:)

#define _delWillStatic1	@selector(formatterWillChangeValueFor::sender:)
#define _delWillStatic2	@selector(formatterWillChangeValueFor::to:sender:)
#define _delDidStatic	@selector(formatterDidChangeValueFor::to:sender:)

#define TEXT_OFFSET	3.0

@implementation BooleanFormatter

- init
{
	font = [Font newFont:"Helvetica" size:12.0];
    newValue = [[DBValue allocFromZone:[self zone]] init];
    return[super init];
}

- free
{
    [newValue free];
    return[super free];
}


- drawFieldAt:(unsigned int)row :(unsigned int)column
    inside:(NXRect *)frame inView:view
    withAttributes:(id <DBTableVectors >)rowAttrs
     :(id <DBTableVectors >)columnAttrs
    usePositions:(BOOL)useRowPos :(BOOL)useColumnPos;
{

    NXPoint             toPoint;
    NXSize              string;
	char				buf[5];
	
    [self getValueAt:row :column withAttributes:rowAttrs :columnAttrs
     usePositions:useRowPos :useColumnPos];

 /*
  * set proper string
  */
    if ([value isNull] || ([value intValue] == 0))
		sprintf(buf, "%s", "NO");
    else
		sprintf(buf,"%s", "YES");
	
 /*
  * Set the size on the font.
  */
  	[font set];    
    string.height = [font pointSize];
    string.width = [font getWidthOf:buf];

    
    toPoint.y = frame->origin.y + frame->size.height -
      (frame->size.height - string.height) / 2;
	toPoint.x = frame->origin.x +
	  (frame->size.width - string.width) / 2 - TEXT_OFFSET;
	
   	PSmoveto(toPoint.x, toPoint.y);
	PSsetgray(NX_BLACK);
	PSshow(buf);
    return self;
}

- mouseDown:(NXEvent *)theEvent at:(int)row :(int)column
    inside:(NXRect *)frame inView:(View *) view
    withAttributes:(id <DBTableVectors >)rowAttrs
     :(id <DBTableVectors >)columnAttrs
    usePositions:(BOOL)useRowPos :(BOOL)useColumnPos
{
    if (theEvent->data.mouse.click < 2)
	return nil;

     /* get the current value */

	[self getValueAt:row :column withAttributes:rowAttrs :columnAttrs
	 usePositions:useRowPos :useColumnPos];

    /* Toggle value */
	if ([value isNull] || ([value intValue] == 0))
	    [newValue setIntValue:1];
	else
	    [newValue setIntValue:0];

	[self setValueAt:row :column
	 withAttributes:rowAttrs :columnAttrs
	 usePositions:useRowPos :useColumnPos];
   

 /* Redraw the modified field */
    [self drawFieldAt:row :column
     inside:frame inView:view
     withAttributes:rowAttrs :columnAttrs
     usePositions:useRowPos :useColumnPos];
    [[view window] flushWindow];

    return self;
}


- setValueAt:(int)row :(int)column
    withAttributes:(id <DBTableVectors >)rowAttrs
     :(id <DBTableVectors >)columnAttrs
    usePositions:(BOOL)useRowPos :(BOOL)useColumnPos
{
    BOOL                isChangeOk = YES;

 /* Ask delegate if we can change */
    if (useRowPos && !useColumnPos && delWill2)
	isChangeOk = [delegate formatterWillChangeValueFor:
		      [columnAttrs identifier]
		      at:row to:newValue sender:self];
    else if (useColumnPos && !useRowPos && delWill2)
	isChangeOk = [delegate formatterWillChangeValueFor:
		      [rowAttrs identifier]
		      at:column to:newValue sender:self];
    else if (delWillStatic2)
	isChangeOk = [delegate formatterWillChangeValueFor:
		      [rowAttrs identifier] :[columnAttrs identifier]
		      to:newValue sender:self];

    if (!isChangeOk)
	return nil;

 /* Tell dataSource our newValue */
    if (useRowPos && !useColumnPos)
	[dataSource setValueFor:[columnAttrs identifier] at:row
	 from:newValue];
    else if (useColumnPos && !useRowPos)
	[dataSource setValueFor:[rowAttrs identifier] at:column
	 from:newValue];
    else
	[dataSource setValueFor:[rowAttrs identifier]
	  :[columnAttrs identifier] from:newValue];

 /* Tell delegate we changed */
    if (useRowPos && !useColumnPos && delDid)
	[delegate formatterDidChangeValueFor:[columnAttrs identifier]
	 at:row to:newValue sender:self];
    else if (!useRowPos && useColumnPos && delDid)
	[delegate formatterDidChangeValueFor:[rowAttrs identifier]
	 at:column to:newValue sender:self];
    else if (delDidStatic)
	[delegate formatterDidChangeValueFor:[rowAttrs identifier]
	  :[columnAttrs identifier] to:newValue sender:self];

    return self;
}

- _setDelegateFlags
{
    delWill1 = delWill2 = delDid = NO;
    delWillStatic1 = delWillStatic2 = delDidStatic = NO;

    if ([delegate respondsTo:_delWill1])
	delWill1 = YES;
    if ([delegate respondsTo:_delWill2])
	delWill2 = YES;
    if ([delegate respondsTo:_delDid])
	delDid = YES;
    if ([delegate respondsTo:_delWillStatic1])
	delWillStatic1 = YES;
    if ([delegate respondsTo:_delWillStatic2])
	delWillStatic2 = YES;
    if ([delegate respondsTo:_delDidStatic])
	delDidStatic = YES;
    return self;
}

- setDelegate:newDelegate
{
    if (newDelegate == delegate)
	return self;
    else
	[super setDelegate:newDelegate];

    [self _setDelegateFlags];

    return self;
}

@end
